/********************
OOR Opportunity Split class
This class shares the Split record with the Secondary owner of the opportunity
********************/
Public Class OpptySplitSharingClass{

    Public static Opportunity_Split__c CreateSplit(Opportunity opty, integer percentOwned, string label, id repId){
        Opportunity_Split__c split = new Opportunity_Split__c();
        UpdateSplit(opty, percentOwned, label, repId, split);
        
        return split;
    }

    Public static void CreateOrUpdateSplit(Opportunity opty, integer percentOwned, string label, id repId, List<Opportunity_Split__c> recycleSplits, List<Opportunity_Split__c> toCreate, List<Opportunity_Split__c> toUpdate){
        if(recycleSplits != null && recycleSplits.size() > 0){
            Opportunity_Split__c split = recycleSplits[0];
            recycleSplits.remove(0);
            UpdateSplit(opty, percentOwned, label, repId, split);
            toUpdate.add(split);         
        }
        else{
            toCreate.add(CreateSplit(opty, percentOwned, label, repId));
        }       
    }
    
    Public static void UpdateSplit(Opportunity opty, integer percentOwned, string label, id repId, Opportunity_Split__c split)
    {
        decimal pctOwned = percentOwned / 100.0;
        split.Owner_ID__c = repId;
        split.Owner_Type__c = label;
        split.Split__c = percentOwned;
        split.Deal_Count__c = pctOwned;

        // Below line added for Prodcution bug fix of owner not able to see his split records
        if(opty.Opportunity_Type__c=='Digital Express' || opty.Opportunity_Type__c=='Bill Cycle Evergreen' ||opty.Opportunity_Type__c=='Net Revenue'
                ||opty.Opportunity_Type__c=='AF Assigned'){
        ListViewIds__c adminId = ListViewIds__c.getInstance();
        if(adminId.SalesforceAdmin__c!=NULL){
        split.OwnerId=adminId.SalesforceAdmin__c;}
        }else{
        split.OwnerId=opty.OwnerId;
        }  
        split.Opportunity__c = opty.id;

        split.Closed_Contract_Net_Revenue__c= Multiply(opty.Closed_Contract_Net_Revenue__c, pctOwned);
        split.Closed_Contract_Revenue__c= Multiply(opty.Closed_Contract_Revenue__c, pctOwned); 
        split.Projected_Revenue__c = Multiply(opty.Revenue_mo__c,pctOwned);
        //split.Projected_Revenue__c = Multiply(opty.SFA_OOR_Projected_Revenue_mo__c, pctOwned); // TODO: Why is Projected_Revenue__c being set twice?!
        split.SOLO_Split_AF_Cancel_Count__c= Multiply(opty.SOLO_AF_Cancel_Count__c, pctOwned);
        split.SOLO_Split_AF_Cancel_mo__c= Multiply(opty.SOLO_AF_Cancel_mo__c, pctOwned);
        split.SOLO_Split_Cancel_Count__c= Multiply(opty.SOLO_Cancel_Count__c, pctOwned);
        split.SOLO_Split_Cancel_mo__c= Multiply(opty.SOLO_Cancel_mo__c, pctOwned);
        split.SOLO_Split_Gross_Sales_mo__c= Multiply(opty.SOLO_Gross_Sales_mo__c, pctOwned);
        split.SOLO_Split_In_Cycle_Decrease_mo__c = Multiply(opty.SOLO_In_Cycle_Decrease_mo__c, pctOwned);
        split.SOLO_Split_In_Cycle_Decr_Count__c= Multiply(opty.SOLO_In_Cycle_Decr_Count__c, pctOwned);
        split.SOLO_Split_In_Cycle_Increase_mo__c = Multiply(opty.SOLO_In_Cycle_Increase_mo__c, pctOwned);
        split.SOLO_Split_In_Cycle_Incr_Count__c= Multiply(opty.SOLO_In_Cycle_Incr_Count__c, pctOwned);
        split.SOLO_Split_New_Cust_Count__c= Multiply(opty.SOLO_New_Cust_Count__c, pctOwned);
        split.SOLO_Split_New_mo__c= Multiply(opty.SOLO_New_mo__c, pctOwned);
        split.SOLO_Split_Off_Cycle_Decrease_mo__c= Multiply(opty.SOLO_Off_Cycle_Decrease_mo__c, pctOwned);
        split.SOLO_Split_Off_Cycle_Decr_Count__c= Multiply(opty.SOLO_Off_Cycle_Decr_Count__c, pctOwned);
        split.SOLO_Split_Off_Cycle_Increase_mo__c= Multiply(opty.SOLO_Off_Cycle_Increase_mo__c, pctOwned);
        split.SOLO_Split_Off_Cycle_Incr_Count__c= Multiply(opty.SOLO_Off_Cycle_Incr_Count__c, pctOwned);
        split.SOLO_Split_Order_Value__c= Multiply(opty.SOLO_Order_Value__c, pctOwned);
        split.SOLO_Split_Prev_Monthly__c= Multiply(opty.SOLO_Prev_Monthly_Amt__c, pctOwned);
        split.SOLO_Split_Prev_Order_Value__c = Multiply(opty.SOLO_Prev_Order_Value__c, pctOwned);
        split.SOLO_Split_Revenue_Closed_Count__c= Multiply(opty.SOLO_Revenue_Closed_Count__c, pctOwned);
        split.SOLO_Split_Revenue_Closed_mo__c= Multiply(opty.SOLO_Revenue_Closed_mo__c, pctOwned);
        split.SOLO_Split_Total_Completed_Orders_Count__c= Multiply(opty.SOLO_Completed_Orders_Count__c, pctOwned);
        split.SOLO_Split_Total_New_Cust_Count__c= Multiply(opty.SOLO_Total_New_Cust_Count__c, pctOwned);
        split.SOLO_Split_Total_New_mo__c= Multiply(opty.SOLO_Total_New_mo__c, pctOwned);
        split.SOLO_Split_Total_Orders_Count__c= Multiply(opty.SOLO_Total_Orders_Count__c, pctOwned);
        split.SOLO_Split_Uncompleted_Orders_mo__c= Multiply(opty.SOLO_Uncompleted_Order_mo__c, pctOwned);
        split.SOLO_Split_Uncompleted_order_Count__c= Multiply(opty.SOLO_Uncompleted_order_Count__c, pctOwned);
        split.SOLO_Split_Win_Back_Count__c= Multiply(opty.SOLO_Win_Back_Count__c, pctOwned);
        split.SOLO_Split_Win_Back_mo__c= Multiply(opty.SOLO_Win_Back_mo__c, pctOwned);
        split.Split_AF_Assigned_Count__c= Multiply(opty.AF_Assigned_Count__c, pctOwned);
        split.Split_AF_Assigned_mo__c= Multiply(opty.AF_Assigned_mo__c, pctOwned);
        split.Split_Bill_Cycle_Evergreen_Count__c= Multiply(opty.Bill_Cycle_Evergreen_Count__c, pctOwned);
        split.Split_Bill_Cycle_Evergreen_mo__c= Multiply(opty.Bill_Cycle_Evergreen_mo__c, pctOwned);
        split.Split_Closed_Rev__c =  Multiply(opty.Monthly_Amount__c, pctOwned);
        split.Split_Order_Up_Down__c =  Multiply(opty.Up_down__c, pctOwned);
        split.Split_Projected_Revenue_mo__c =  Multiply(Opty.Opportunity_Amount__c, pctOwned);
        split.Split_Projected_Up_Down__c =  Multiply(opty.Projected_Up_Down__c, pctOwned);
        split.Split_SOLO_Closed_Up_Down__c =  Multiply(opty.Closed_Up_Down__c, pctOwned);
        split.Split_SOLO_Contract_Rev_mo__c= Multiply(opty.SOLO_Contract_Revenue_mo__c, pctOwned);
        split.Split_SOLO_Contract_Up_Down__c= Multiply(opty.SOLO_Contract_Up_Down__c, pctOwned);
        split.Split_Net_Revenue_mo__c=Multiply(opty.Net_Rev_mo__c, pctOwned);
        split.Split_Net_Revenue_count__c=Multiply(opty.Net_Rev_Count__c, pctOwned);
        split.Split_Digital_Express_mo__c=Multiply(opty.Digital_Express_mo__c, pctOwned);
        split.Split_Digital_Express_Order_Count__c=Multiply(opty.Digital_Express_Orders_Count__c, pctOwned);
        Split.Split_Bill_Cycle_Evergreen_mo__c=Multiply(opty.Bill_Cycle_Evergreen_mo__c, pctOwned);
        Split.Split_Bill_Cycle_Evergreen_Count__c=Multiply(opty.Bill_Cycle_Evergreen_Count__c, pctOwned);

    }
    
    private static decimal Multiply(decimal x, decimal y)
    {
        if(x == null || y == null)
            return 0;
            
        return x * y;
    }
    
    public void deleteShares(List<ID> osList){
        List<Opportunity_Split__Share> shares = [SELECT Id, ParentId FROM Opportunity_Split__Share where rowCause = 'Split_Owner_Sharing__c' and ParentId in :osList];
        if(shares.size() > 0)
            delete shares;
    }
    Public void DeleteOpptyShare(Set<Id> DeleteShare){
        List<Opportunity_Split__Share> OShareDelete = new List<Opportunity_Split__Share>();
        OShareDelete = [Select id from Opportunity_Split__Share where ParentId IN:DeleteShare AND RowCause =: Schema.Opportunity_Split__Share.RowCause.Split_Owner_Sharing__c];
        If(OShareDelete.size()>0){
            try{
                Delete OShareDelete;
            }
            Catch(DMLException ex){
                System.debug('DMLException'+ex);
            }
        }
    }
    Public void OpptyShare(List<Opportunity_Split__c> OSlist,Set<Id> DeleteSharing){
        DeleteOpptyShare(DeleteSharing);
       
       //Start:Added Code for resolve inactive User Sharing Issue
        List<ID> idList = new List<ID>(); 
         for(Opportunity_Split__c OSId:OSlist){
            idList.add(OSId.Owner_ID__c);
         }        
        
       //  List<User> userlist = [SELECT Id, IsActive FROM User where Id in :idList];
        Map<Id,User> UserStatus = new Map<ID,User>();
        
         for(User userId :[SELECT Id, IsActive FROM User where Id in :idList])
         {
            UserStatus.put(userId.Id,userId);
         } 
        
        
        //End: Added Code for resolve inactive User Sharing Issue
        
        List<Opportunity_Split__Share> OShare = new List<Opportunity_Split__Share>();
        
        Opportunity_Split__Share SpShr;
        Map<id,Opportunity_Split__c> OSMap = new Map<id,Opportunity_Split__c>();
        for(Opportunity_Split__c OS:OSlist){
            SpShr = new Opportunity_Split__Share();
            System.debug('UserStatus.get(OS.Owner_ID__c)'+UserStatus.get(OS.Owner_ID__c));
          //Start: Added Code for resolve inactive User Sharing Issue
          if(UserStatus.get(OS.Owner_ID__c)!=null && UserStatus.get(OS.Owner_ID__c).IsActive){
          //End: Added Code for resolve inactive User Sharing Issue
            SpShr.ParentId = OS.Id;
            SpShr.UserOrGroupId = OS.Owner_ID__c;
            SpShr.AccessLevel = 'Edit';
            SpShr.RowCause = Schema.Opportunity_Split__Share.RowCause.Split_Owner_Sharing__c;
            OSMap.put(OS.id,OS);
            OShare.add(SpShr);
          }
         //Start: Added Code for resolve inactive User Sharing Issue
        }
        //End: Added Code for resolve inactive User Sharing Issue
        Database.SaveResult[] lsr = Database.insert(OShare,false);
        
        Integer i=0;
            for(Database.SaveResult sr : lsr){
                if(!sr.isSuccess()){
                    Database.Error err = sr.getErrors()[0];
                        if(!(err.getStatusCode() == StatusCode.FIELD_FILTER_VALIDATION_EXCEPTION && err.getMessage().contains('AccessLevel'))){
                                OSMap.get(OShare[i].parentId).addError('Unable to grant sharing access due to following exception:' + err.getMessage());
                        }
                }
                i++;
            }
        }
}